/**
 * $Id: GZSubmit851MTThread.java,v 1.1 2006/09/06 08:06:06 martin Exp $
 *
 * Copyright 2005 Skyinfo, Inc. All Rights Reserved.
 */
package com.haoxi.gateway.runner.gzunicom;

import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Date;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.haoxi.gateway.common.CommonMsgBean;
import com.haoxi.gateway.common.Queue;
import com.haoxi.gateway.common.SQLConst;
import com.haoxi.gateway.common.SYSConst;
import com.haoxi.gateway.connector.Connector;
import com.haoxi.gateway.runner.AbsOutQueue;
import com.haoxi.gateway.runner.IRun;
import com.haoxi.gateway.runner.RunnerMgr;
import com.haoxi.gateway.runner.smscommand.SubmitCmd;
import com.haoxi.gateway.util.db.DBConnectUtil;

public class GZSubmit851MTThread implements IRun {

    private Connector conn;
    private Queue queue;
    Queue reciveQueue;
    private boolean running = false;
    private Date createTime;
    private Date lastRunTime;
    private int run_stat = IRun.RUNNER_READY;
    private String name;
    private Map submitRespMap;
    private static final Log log = LogFactory.getLog(GZSubmit851MTThread.class);
    public static final int PROC_NORMAL = 2;

    public static final int PROC_RETRY = 4;

    public static final int PROC_ERROR = 8;

    public GZSubmit851MTThread(Queue toQueue, Queue reciveQueue, Connector con,
            Map aMap) {
        this.submitRespMap = aMap;
        this.conn = con;
        queue = toQueue;
        this.reciveQueue = reciveQueue;
        this.name = toQueue.getName();
        createTime = new Date();
        if (conn == null || submitRespMap == null) {
            log
                    .error("Submit851MTThread init error (conn == null || submitRespMap == null)");
        }
        setName(con.getConnName() + "Thread");
    }

    public void run() {
        log.debug("Out Queue:" + name + " start !!!");

        // check queue
        if (queue == null) {
            return;
        }

        // prepare running
        queue.addChengeListener(this);
        running = true;
        lastRunTime = new Date();
        Object obj;
        obj = null;
        while (running) {
            run_stat = IRun.RUNNER_RUNNING;
            lastRunTime.setTime(System.currentTimeMillis());
            try {
                Thread.sleep(1000);
                int queueLen = queue.getLength();
                // 队列长度大于0
                if (queueLen > 0) {
                    // 建立连接
                    conn.disConnected();
                    boolean bol = conn.openConnect();
                    conn.setSocketKeepLive(bol);
                    if (bol) {
                        // 发送消息
                        while (!queue.isEmpty()) {
                            obj = queue.sub();
                            if (null != obj) {
                                this.doJob(obj, queueLen);
                            }
                        }
                    }
                }
            } catch (InterruptedException e) {
                log.debug("////////////// wake up ///////////////");
            } catch (Exception e) {
                log.error("", e);
            }
        }// end of while
    }

    // get threader object create time
    public Date getCreateTime() {
        return createTime;

    }

    // get threader object last run time
    public Date getLastRunTime() {
        return lastRunTime;
    }

    // get threader object run interval time
    public long getSleepTime() {
        return 0;
    }

    // set threader object run interval time
    public void setSleepTime(long sleepTime) {

    }

    // get threader object is running
    public boolean isRunning() {
        return running;
    }

    // set threader object is running or not
    public void setStop() {

    }

    public int getStatus() {
        return this.run_stat;
    }

    public String getName() {
        return name;
    }

    public void setName(String sName) {

    }

    public int doJob(Object pObject, int queueLen) {
        int nRet = AbsOutQueue.PROC_ERROR;
        if (pObject instanceof CommonMsgBean) {
            // send message
            CommonMsgBean msgObj = (CommonMsgBean) pObject;
            // 若下发的是MT，记录MT到Map中
            Object cmd = msgObj.getReserve();
            if (cmd instanceof SubmitCmd) {
                SubmitCmd submitMtCmd = (SubmitCmd) cmd;
                String submitTime = SQLConst.dateformat.format(new Date());
                // 记录下发时间
                submitMtCmd.setSubmitTime(submitTime);
                // 保存MT信息到MYSQL
                if (saveSendedMT(submitMtCmd)) {
                    try {
                        if (conn.writeProtcol(msgObj)) {
                            reciveQueue.add(conn.readProtcol());
                            // record SendMT_NoResp_Count ++
                            conn.increaseSendMTNoRespCount();
                            nRet = AbsOutQueue.PROC_NORMAL;
                            log.debug("Send MT sucessfully! "
                                    + submitMtCmd.toString());
                        } else {
                            nRet = AbsOutQueue.PROC_ERROR;
                            log.error("Send MT unsucessfully！"
                                    + submitMtCmd.toString());
                            this.deleteSendedMT(submitMtCmd.getSequence());
                        }
                    } catch (IOException ex) {
                        this.deleteSendedMT(submitMtCmd.getSequence());
                        nRet = AbsOutQueue.PROC_ERROR;
                        // 断开连接
                        conn.disConnected();
                        log.error("send submit MT msg IOException:", ex);
                    }
                } else {
                    log
                            .error("Send MT unsucessfully!"
                                    + submitMtCmd.toString());
                    nRet = AbsOutQueue.PROC_ERROR;
                }
            }
        }
        return nRet;
    }

    /**
     * delete Sended MT for need submitStatsu.
     * 
     * @param mt
     */
    private void deleteSendedMT(String sequenceID) {
        if (null == sequenceID) {
            log.error("SubmitThread.deleteSendedMT() IlleagalArgument! ");
            return;
        }
        // put the NeedRespMTData into submitRespMap
        synchronized (submitRespMap) {
            submitRespMap.remove(sequenceID);
        }
        // save NeedRespMTData into Mysql DB
        Connection conn = null;
        PreparedStatement ps = null;
        String gateway_DBName = (String) RunnerMgr.getInstance()
                .getSystemConf().get(SYSConst.CONF_DB_MYSQL);
        try {
            conn = DBConnectUtil.open(gateway_DBName);
            ps = conn
                    .prepareStatement(SQLConst.DELETE_NEED_SUBMITSTATUS_MTDATA);
            ps.setString(1, sequenceID);

            if (1 != ps.executeUpdate()) {
                log
                        .error("SubmitThread.deleteSendedMT() delete MT data into MYsql DB Failed, MT's sequence: ["
                                + sequenceID + "]");
            }
        } catch (SQLException e) {
            log.error("SQLException:", e);
            log
                    .error("SubmitThread.deleteSendedMT() delete MT data into MYsql DB Failed, MT's sequence: ["
                            + sequenceID + "]");
        } catch (Exception e) {
            log.error("other Exception:", e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                log.error("close:", e);
            }
        }
    }

    /**
     * save Sended MT for need submitStatsu.
     * 
     * @param mt
     */
    private boolean saveSendedMT(SubmitCmd mt) {
        boolean result = false;
        // save NeedRespMTData into Mysql DB
        Connection conn = null;
        PreparedStatement ps = null;
        String gateway_DBName = (String) RunnerMgr.getInstance()
                .getSystemConf().get(SYSConst.CONF_DB_MYSQL);
        try {
            // put the NeedRespMTData into submitRespMap
            synchronized (submitRespMap) {
                // log.warn("--------------send mt.getSequence() = " +
                // mt.getSequence()+"-------------------");
                submitRespMap.put(mt.getSequence(), mt);
            }

            conn = DBConnectUtil.open(gateway_DBName);
            ps = conn.prepareStatement(SQLConst.SAVE_NEED_SUBMITSTATUS_MTDATA);
            ps.setString(1, mt.getSequence());
            ps.setInt(2, mt.getStype());
            ps.setString(3, mt.getServiceId());
            ps.setString(4, mt.getOrgMobile());
            ps.setInt(5, mt.getOrgMobileType());
            ps.setString(6, mt.getDestMobile());
            ps.setInt(7, mt.getDestMobileType());
            ps.setString(8, mt.getFeeMobile());
            ps.setInt(9, mt.getFeeMobileType());
            ps.setString(10, mt.getFeeType());
            ps.setInt(11, mt.getFeeCode());
            ps.setString(12, mt.getMsgContent());
            ps.setInt(13, mt.getProvice());
            ps.setInt(14, mt.getCity());
            ps.setString(15, mt.getCityName());
            ps.setString(16, mt.getLinkID());
            ps.setInt(17, mt.getCp());
            ps.setString(18, mt.getSubmitTime());
            ps.setString(19, mt.getGateWayCode());
            ps.setString(20, mt.getSid());
            ps.setString(21, mt.getMomtRelateID());
            if (1 != ps.executeUpdate()) {
                log
                        .error("Syncronize for add Sended MT data into MYsql DB Failed, MT's sequence: ["
                                + mt.getSequence() + "]");
            }
            result = true;
        } catch (SQLException e) {
            result = false;
            log.error("SQLException:", e);
            log
                    .error("Syncronize for add Sended MT data into MYsql DB Failed, MT's sequence: ["
                            + mt.getSequence() + "]");
        } catch (Exception e) {
            result = false;
            log.error("other Exception:", e);
        } finally {
            try {
                if (ps != null) {
                    ps.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException e) {
                log.error("close:", e);
            }
        }
        return result;
    }
}
